package com.jwpdk.dbframework;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

import org.apache.log4j.Logger;

import com.jwpdk.common.Config;
/**
 * 
 * @author 王志伟
 *
 */
public class DBFactory {

	private final Logger		log	= Logger.getLogger(this.getClass());
	private static DBFactory	dbFactory;
	private static Config		config;
	private Connection			conn;

	private DBFactory() {
		config = Config.getInstance();
	}

	public static DBFactory getInstance() {
		if ( dbFactory == null || Config.SYSTEM_MODE_DEBUG.equals(config.getSysMode()) ) {
			dbFactory = new DBFactory();
		}
		return dbFactory;
	}

	/**
	 * 获取数据库连接
	 * @return
	 */
	public Connection getConnection() throws Exception {
		if ( config.getDBMode().equalsIgnoreCase(Config.DB_CON_JDBC) ) {
			loadConnectionForJDBC();
		} else if ( config.getDBMode().equalsIgnoreCase(Config.DB_CON_JNDI) ) {
			loadConnectionForJNDI();
		}

		return conn;
	}

	/**
	 * 获取DAO对象
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public IDAO getDao() throws Exception {
		String daoImplClass = "";
		if ( "".equals(config.getDAOImpl()) ) {
			switch ( config.getDBType() ) {
				case Config.DB_TYPE_ORACLE :
					daoImplClass = "com.jwpdk.dbframework.impl.OracleBaseDAO";
					break;
				case Config.DB_TYPE_MYSQL :
					daoImplClass = "com.jwpdk.dbframework.impl.MysqlBaseDAO";
					break;
				case Config.DB_TYPE_SQLSERVER :
					daoImplClass = "com.jwpdk.dbframework.impl.SqlServerBaseDAO";
					break;
				default:
					daoImplClass = "com.jwpdk.dbframework.impl.OracleBaseDAO";
					break;
			}
		} else {
			daoImplClass = config.getDAOImpl();
		}
		if ( log.isDebugEnabled() ) {
			log.debug("daoImplClass:" + daoImplClass);
		}
		Object o = null;
		try {
			Class< IDAO> iclass = (Class< IDAO>) Class.forName(daoImplClass);
			o = iclass.newInstance();
			if ( !IDAO.class.isAssignableFrom(o.getClass()) )
				throw new Exception(daoImplClass + " 未实现 com.jwpdk.dbframework.IDAO 接口！");

			if ( !DAOBase.class.isAssignableFrom(o.getClass()) )
				throw new Exception(daoImplClass + " 未继承 com.jwpdk.dbframework.DAOBase 超类！");

		} catch ( ClassNotFoundException e ) {
			log.error("未找到" + daoImplClass + "类！");
			throw e;
		} catch ( Exception e ) {
			log.error(e);
			throw e;
		}
		return (IDAO) o;
	}

	/**
	 * JNDI方式获取数据库连接
	 */
	private void loadConnectionForJNDI() throws Exception {
		Context ctx = null;
		DataSource ds = null;
		try {
			ctx = new InitialContext();
			ds = (DataSource) ctx.lookup("java:comp/env/jdbc/" + config.getJNDIStr());
			conn = ds.getConnection();
		} catch ( Exception e ) {
			log.error(e);
			throw e;
		} finally {
			try {
				if ( ctx != null ) {
					ctx.close();
				}
			} catch ( NamingException e ) {
				log.error(e);
				throw e;
			}
		}
	}

	/**
	 * JDBC方式获取数据库连接
	 */
	private void loadConnectionForJDBC() throws Exception {
		String driver = "";
		switch ( config.getDBType() ) {
			case Config.DB_TYPE_ORACLE :
				driver = "oracle.jdbc.driver.OracleDriver";
				break;
			case Config.DB_TYPE_MYSQL :
				driver = "org.gjt.mm.mysql.Driver";
				break;
			case Config.DB_TYPE_SQLSERVER :
				driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
				break;
			default:
				driver = "oracle.jdbc.driver.OracleDriver";
				break;
		}
		log.debug("driver:" + driver);
		try {
			Class.forName(driver);
			log.debug("url:" + config.getDBURL());
			log.debug("DBParameters:" + config.getDBParameters());
			conn = DriverManager.getConnection(config.getDBURL(),config.getDBParameters());
		} catch ( Exception e ) {
			log.error(e);
			conn = null;
			throw e;
		} finally {
			try {
				if ( conn != null ) {
					conn.setAutoCommit(false);
				}
			} catch ( SQLException e ) {
				log.error(e);
				throw e;
			}
		}
		log.debug("connection:" + conn);
	}

}
